package com.bocloud.cmp.driver.providers.os;

import java.util.List;

import org.openstack4j.api.Builders;
import org.openstack4j.api.exceptions.ClientResponseException;
import org.openstack4j.model.common.ActionResponse;
import org.openstack4j.model.network.AttachInterfaceType;
import org.openstack4j.model.network.Router;
import org.openstack4j.model.network.RouterInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bocloud.cmp.driver.convertor.BeanConvert;
import com.bocloud.cmp.driver.convertor.os.ConvertRoute;
import com.bocloud.cmp.driver.providers.RouterDriver;
import com.bocloud.cmp.model.RouteModel;
import com.bocloud.common.model.BsmResult;
import com.google.common.collect.Lists;

public class OSRouterDriver extends OSDriver implements RouterDriver {

    private static Logger logger = LoggerFactory.getLogger(OSRouterDriver.class);

    public OSRouterDriver() {
        super();
    }

    public OSRouterDriver(String endpoint, String username, String password, String tenant, String domain,
            String project, Version version) {
        super(endpoint, username, password, tenant, domain, project, version);
    }

    @Override
    public BsmResult sync() {
        List<RouteModel> models = Lists.newArrayList();
        List<? extends Router> routers = Lists.newArrayList();
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        routers = this.getClient().networking().router().list();
        if (null != routers) {
            BeanConvert<RouteModel, Router> convertRoute = new ConvertRoute();
            models = convertRoute.convertList(routers);
        }
        return new BsmResult(true, models, "success");
    }

    @Override
    public BsmResult create(RouteModel routeModel) {

        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        Router routeBuilder = BuildRouter(routeModel);
        Router route = this.getClient().networking().router().create(routeBuilder);

        if (null != route) {
            BeanConvert<RouteModel, Router> convertRoute = new ConvertRoute();
            return new BsmResult(true, convertRoute.convertModel(route), "创建成功!");
        }
        return new BsmResult(false, "创建路由失败");
    }

    @Override
    public BsmResult remove(String routerId) {

        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        try {
            ActionResponse actionResponse = this.getClient().networking().router().delete(routerId);
            if (actionResponse.isSuccess()) {
                return new BsmResult(true, "success");
            }
        } catch (ClientResponseException e) {
            return new BsmResult(false, "删除路由失败");
        }
        return new BsmResult(false, "删除路由失败");
    }

    @Override
    public BsmResult detail(String routerId) {
        // this.getClient().networking().router().
        return null;
    }

    @Override
    public BsmResult modify(RouteModel routeModel) {
        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        Router routeBuilder = BuildRouter(routeModel);
        if (null == routeBuilder) {
            return new BsmResult(false, "更新路由参数失败");
        }
        Router route = null;
        try {
            route = this.getClient().networking().router().update(routeBuilder);
        } catch (ClientResponseException e) {
            logger.error("Update Route [{}} failed {} ", route.getId(), e);
            return new BsmResult(false, "更新路由失败");
        }
        if (null != route) {
            BeanConvert<RouteModel, Router> convertRoute = new ConvertRoute();
            return new BsmResult(true, convertRoute.convertModel(route), "更新路由成功!");
        }
        return new BsmResult(false, "更新路由失败");
    }

    private Router BuildRouter(RouteModel routeModel) {
        if (null == routeModel) {
            return null;
        }
        if (null != routeModel.getNetworkId()) {
            return Builders.router().name(routeModel.getName()).adminStateUp(routeModel.getAdminStateup())
                    .externalGateway(routeModel.getNetworkId()).id(routeModel.getRouteId()).build();
        } else {
            return Builders.router().name(routeModel.getName()).adminStateUp(routeModel.getAdminStateup())
                    .id(routeModel.getRouteId()).build();
        }

    }

    /**
     * 
     * @param routeId
     * @param type
     *            (port subnet)
     * @param portId
     * @return
     */
    public BsmResult attachInterface(String routeId, String type, String portId) {

        RouterInterface routeInterface = this.getClient().networking().router().attachInterface(routeId,
                AttachInterfaceType.valueOf(type), portId);
        return new BsmResult(true, routeInterface, "sucess");

    }

}
